package com.example.demo.poc.example;

import com.googlecode.aviator.runtime.function.AbstractVariadicFunction;
import com.googlecode.aviator.runtime.type.AviatorNil;
import com.googlecode.aviator.runtime.type.AviatorObject;
import com.googlecode.aviator.runtime.type.AviatorRuntimeJavaType;

import java.math.BigDecimal;
import java.util.List;
import java.util.Map;

public class AviatorSumFunction extends AbstractVariadicFunction{

    private static final long serialVersionUID = -5615893301837686269L;

    public static final String NAME = "sum";

    @Override
    public String getName() {
        return NAME;
    }

    @Override
    public AviatorObject variadicCall(Map<String, Object> map, AviatorObject... args) {
        if (args == null || args.length == 0) {
            return AviatorNil.NIL;
        }
        BigDecimal val = BigDecimal.valueOf(0L);
        boolean hasDouble = false;
        for (int i = 0; i < args.length; i++) {
            Object o = args[i].getValue(map);
            if(o instanceof Long){
                val= val.add(BigDecimal.valueOf((Long)o));
            }else if(o instanceof Double) {
                hasDouble = true;
                val= val.add(BigDecimal.valueOf((Double)o));
            }else if(o.getClass().isArray()){
                val= val.add(getSumValue((Object[])o));

            }else if (o instanceof java.util.List){
                val= val.add(getSumValue((List)o));
            }
        }
        if(!hasDouble) {
            return AviatorRuntimeJavaType.valueOf(val.longValue());
        }else{
            return AviatorRuntimeJavaType.valueOf(val.doubleValue());
        }
    }

    private BigDecimal getSumValue(Object[] o){
        BigDecimal val = BigDecimal.valueOf(0L);
        if (o == null || o.length == 0) {
            return val;
        }
        for (int i = 0; i < o.length; i++) {
            if(o[i] instanceof Long){
                val= val.add(BigDecimal.valueOf((Long)o[i]));
            }else if(o[i] instanceof Double) {
                val= val.add(BigDecimal.valueOf((Double)o[i]));
            }
        }
        return val;
    }


    private BigDecimal getSumValue(List o){
        BigDecimal val = BigDecimal.valueOf(0L);
        if (o == null || o.size() == 0) {
            return val;
        }
        for (int i = 0; i < o.size(); i++) {
            if(o.get(i) instanceof Long){
                val= val.add(BigDecimal.valueOf((Long)o.get(i)));
            }else if(o.get(i) instanceof Double) {
                val= val.add(BigDecimal.valueOf((Double)o.get(i)));
            }
        }
        return val;
    }
}
